var EasyMongo = require("../../common").EasyMongo;
var mapping = require("../../common").Mapping;
var _ = require("underscore");
var iconv = require('iconv-lite');

var CREATE = 0,READ = 1,UPDATE = 2,DELETE = 3;

exports.displayDataPage = function (req, res) {
    EasyMongo.find("meta", {collectionName: req.params.name}, function (err, docs) {
        if (err) res.render("errorTpl", mapping.errorCode.basicServerError);
        else {
            if (docs.length == 0) {
                res.render("errorTpl", mapping.errorCode.paramError);
            } else if (docs.length > 1) {
                res.render("errorTpl", mapping.errorCode.dirtyDataError);
            } else {
                res.render("displayDataTpl", docs[0]);
            }
        }
    });

    /**
     * inject _id to hidden field as key to get other operation
     * */
};

exports.displayConfigData = function (req, res) {
    EasyMongo.find("meta", {_id: req.params.id}, function (err, docs) {
        if (err) res.send(mapping.errorCode.basicServerError);
        else {
            if (docs.length == 0) {
                res.send(mapping.errorCode.paramError);
            } else if (docs.length > 1) {
                res.send(mapping.errorCode.dirtyDataError);
            } else {
                res.send(docs[0]);
            }
        }
    });
};

exports.findCollectionData = function (req, res) {
    EasyMongo.find("meta", {_id: req.params.id}, function (err, docs) {
        if (err) res.send(mapping.errorCode.basicServerError);
        else {
            if (docs.length == 0) {
                res.send(mapping.errorCode.paramError);
            } else if (docs.length > 1) {
                res.send(mapping.errorCode.dirtyDataError);
            } else {
                if(!docs[0].crud[READ]) {
                    res.send(mapping.errorCode.privilegeError);
                    return;
                }
                var obj = {};
                var filter = {};
                var dateValue = {};
                docs[0].columns.forEach(function (e) {
                    if (!e.isDisplay) {
                        obj[e.columnName] = 0;
                    }
                    if (e.dataType == 'date') {
                        dateValue[e.columnName] = true;
                        filter[e.columnName] = function (data) {
                            return new Date(data).Format(e.filter || "yyyy/MM/dd hh:mm");
                        };
                    } else if (e.filter) {
                        var tempCode = e.filter.code.substring(e.filter.code.indexOf('{') + 1, e.filter.code.lastIndexOf('}'));
                        filter[e.columnName] = new Function("data", tempCode);
                    }
                });

                /* check if is date, get time tick */
                for(var single in req.query.where) {
                    if(single in dateValue) {
                        req.query.where[single].$lt && (req.query.where[single].$lt = parseInt(req.query.where[single].$lt));
                        req.query.where[single].$gt && (req.query.where[single].$gt = parseInt(req.query.where[single].$gt));
                    }
                }
                EasyMongo.find(docs[0].collectionName, req.query.where || {}, obj, function (err, data) {
                    if (err) res.send(mapping.errorCode.paramError);
                    else {
                        res.send({
                            data: (function () {
                                var res = [];
                                /* sort result */
                                data.sort(function (a, b) {
                                    var keyNum = 0;
                                    var result = 0;
                                    result = (function sortByProperties() {
                                        result = 0;
                                        if (keyNum < docs[0].sortKey.length) {
                                            for(var i in docs[0].sortKey[keyNum]) {
                                                if (typeof a[i] !== 'string' && typeof a[i] !== 'number') {
                                                    ++keyNum;
                                                    return sortByProperties();
                                                }
                                                var compareResult;
                                                if(typeof a[i] === 'number' && typeof b[i] === 'number')
                                                    compareResult = a[i] - b[i];
                                                 else
                                                    compareResult = (a[i] + "").localeCompare(b[i] + "");
                                                if (compareResult != 0) {
                                                    return !docs[0].sortKey[keyNum][i].match(/desc/i) ? compareResult : -compareResult;
                                                } else {
                                                    ++keyNum;
                                                    return sortByProperties();
                                                }
                                            }
                                        } else {
                                            return result;
                                        }
                                    })();
                                    return result;
                                });

                                /* pluck data */
                                for (var i = 0; i < data.length; i++) {
                                    if (i < req.query.option.page[0] * req.query.option.page[1] && i >= (req.query.option.page[0] - 1) * req.query.option.page[1]) {
                                        for (var j in data[i]) {
                                            if (j in filter) {
                                                data[i][j] = filter[j](data[i][j]);
                                            }
                                        }
                                        res.push(data[i]);
                                    }
                                }
                                return res;
                            })(), count: data.length
                        });
                    }
                });
            }
        }
    });
};

exports.addCollectionData = function (req, res) {
    EasyMongo.find("meta", {_id: req.params.id}, function (err, docs) {
        if (err) res.send(mapping.errorCode.basicServerError);
        else {
            if (docs.length == 0) {
                res.send(mapping.errorCode.paramError);
            } else if (docs.length > 1) {
                res.send(mapping.errorCode.dirtyDataError);
            } else {
                if(!docs[0].crud[CREATE]) {
                    res.send(mapping.errorCode.privilegeError);
                    return;
                }
                //todo impl
                res.send("success");
            }
        }
    });
};

exports.updateCollectionData = function (req, res) {
    EasyMongo.find("meta", {_id: req.params.id}, function (err, docs) {
        if (err) res.send(mapping.errorCode.basicServerError);
        else {
            if (docs.length == 0) {
                res.send(mapping.errorCode.paramError);
            } else if (docs.length > 1) {
                res.send(mapping.errorCode.dirtyDataError);
            } else {
                if(!docs[0].crud[UPDATE]) {
                    res.send(mapping.errorCode.privilegeError);
                    return;
                }
                var i = 0;
                (function queryUpdate() {
                    if (i < req.body.data.length) {
                        req.body.data[i].update = _.omit(req.body.data[i].update, "_id");
                        for (var prop in req.body.data[i].update) {
                            docs[0].columns.forEach(function (col) {
                                if (col.columnName == prop && col.deFilter) {
                                    req.body.data[i].update[prop] = (new Function("data",
                                        col.deFilter.code.substring(
                                            col.deFilter.code.indexOf('{') + 1,
                                            col.deFilter.code.lastIndexOf("}"))))(req.body.data[i].update[prop]);
                                }
                            });
                        }
                        EasyMongo.update(docs[0].collectionName, {_id: req.body.data[i].where}, req.body.data[i].update, function (err) {
                            if (err) {
                                console.log(err);
                                res.send("error");
                                return;
                            }
                        });
                        i++;
                        queryUpdate();
                    } else {
                        res.send("success");
                    }
                })();
            }
        }
    });
};


exports.removeCollectionData = function (req, res) {
    EasyMongo.find("meta", {_id: req.params.id}, function (err, docs) {
        if (err) res.send(mapping.errorCode.basicServerError);
        else {
            if (docs.length == 0) {
                res.send(mapping.errorCode.paramError);
            } else if (docs.length > 1) {
                res.send(mapping.errorCode.dirtyDataError);
            } else {
                if(!docs[0].crud[DELETE]) {
                    res.send(mapping.errorCode.privilegeError);
                    return;
                }
                //todo impl
                res.send("success");
            }
        }
    });
};

exports.exportCollectionData = function (req, res) {
    EasyMongo.find("meta", {_id: req.params.id}, function (err, docs) {
        if (err) res.send(mapping.errorCode.basicServerError);
        else {
            if (docs.length == 0) {
                res.send(mapping.errorCode.paramError);
            } else if (docs.length > 1) {
                res.send(mapping.errorCode.dirtyDataError);
            } else {
                var obj = {};
                var filter = {};
                var dateValue = {};
                docs[0].columns.forEach(function (e) {
                    if (!e.isDisplay) {
                        obj[e.columnName] = 0;
                    }

                    if (e.dataType == 'date') {
                        dateValue[e.columnName] = true;
                        filter[e.columnName] = function (data) {
                            return new Date(data).Format(e.filter || "yyyy/MM/dd hh:mm");
                        };
                    } else if (e.filter) {
                        var tempCode = e.filter.code.substring(e.filter.code.indexOf('{') + 1, e.filter.code.lastIndexOf('}'));
                        filter[e.columnName] = new Function("data", tempCode);
                    }
                });
                obj._id = 0;
                /* check if is date, get time tick */
                for(var single in req.query.query) {
                    if(single in dateValue) {
                        req.query.query[single].$lt && (req.query.query[single].$lt = parseInt(req.query.query[single].$lt));
                        req.query.query[single].$gt && (req.query.query[single].$gt = parseInt(req.query.query[single].$gt));
                    }
                }
                EasyMongo.find(docs[0].collectionName, eval("(" + req.query.query + ")"), obj, function (err, data) {
                    if (err) res.send(mapping.errorCode.paramError);
                    else {
                        /* sort result */
                        data.sort(function (a, b) {
                            var keyNum = 0;
                            var result = 0;
                            result = (function sortByProperties() {
                                result = 0;
                                if (keyNum < docs[0].sortKey.length) {
                                    for(var i in docs[0].sortKey[keyNum]) {
                                        if (typeof a[i] !== 'string' && typeof a[i] !== 'number') {
                                            ++keyNum;
                                            return sortByProperties();
                                        }
                                        var compareResult;
                                        if(typeof a[i] === 'number' && typeof b[i] === 'number')
                                            compareResult = a[i] - b[i];
                                        else
                                            compareResult = (a[i] + "").localeCompare(b[i] + "");
                                        if (compareResult != 0) {
                                            return !docs[0].sortKey[keyNum][i].match(/desc/i) ? compareResult : -compareResult;
                                        } else {
                                            ++keyNum;
                                            return sortByProperties();
                                        }
                                    }
                                } else {
                                    return result;
                                }
                            })();
                            return result;
                        });

                        var content = "";
                        for (var i in data[0]) {
                            content += i + ",";
                        }
                        content += '\n'
                        data.forEach(function (e) {
                            for (var i in e) {
                                filter[i] && (e[i] = filter[i](e[i]));
                                e[i] && e[i].replace && (e[i] = e[i].replace(/\s/g, " "));
                                content += e[i] ? ("\t" + e[i] + "\t,") : "\t,\t";
                            }
                            content += "\n";
                        });
                        res.setHeader("Content-type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                        res.setHeader("Content-Disposition", "attachment;filename=" + encodeURIComponent("ExceptionReport.csv"));
                        res.setHeader("Expires", "0");
                        res.setHeader("Cache-Control", "no-cache, must-revalidate");
                        res.setHeader("Pragma", "no-cache");
                        var buffer = new Buffer("\ufeff" + content);
                        if(!docs[0].crud[READ]) {
                            res.send(mapping.errorCode.privilegeError);
                        } else {
                            res.send(iconv.encode(buffer, 'utf8'));
                        }
                    }
                });
            }
        }
    });
};